package com.constructiveproof.example.auth

import org.scalatra.auth.{ScentryConfig, ScentrySupport}
import com.constructiveproof.example.models.User
import org.scalatra.{ScalatraBase}
import org.slf4j.LoggerFactory
import com.constructiveproof.example.auth.strategies.{RememberMeStrategy, UserPasswordStrategy}

/**
* 身份验证的配置入口
*
*/
trait AuthenticationSupport extends ScalatraBase with ScentrySupport[User] {
  self: ScalatraBase =>
  
  //两个函数是获取User信息时调用的函数
  //一般情况下不需要覆写
  
  //每一个（通过验证的请求的）请求进来，执行一次，保持数据有效性
  protected def fromSession = {
    case id: String => {
      println("调用了fromSession")
      User(id)
    }
  }
  
  //只在执行完验证策略通过之后调用一次，获得一个Id缓存下来，交由fromsession来获取user对象
  protected def toSession   = {
    case usr: User => {
      println("调用了toSession")
      usr.id
    }
  }

  protected val scentryConfig = (new ScentryConfig {
    override val login = "/sessions/new"
  }).asInstanceOf[ScentryConfiguration]

  val logger = LoggerFactory.getLogger(getClass)
  
  /**
    * 如果没有登陆，跳转到登陆页面
    */
  protected def requireLogin() = {
    if(!isAuthenticated) {
      redirect(scentryConfig.login)
    }
  }


  /**
    * 如果未经身份验证的用户试图访问一个路由，会受到安全保护，
    * 运行在UserPasswordStrategy（密码验证策略）unauthenticated()方法。
    */
  override protected def configureScentry = {
    scentry.unauthenticated {
      scentry.strategies("UserPassword").unauthenticated()
    }
  }

  /**
   * Register auth strategies with Scentry. Any controller with this trait mixed in will attempt to
   * progressively use all registered strategies to log the user in, falling back if necessary.
    * 用户身份验证的策略，任何混入这个特质的控制器都会，逐步执行这里注册的验证策略。
   */
  override protected def registerAuthStrategies = {
    scentry.register("UserPassword", app => new UserPasswordStrategy(app))
    scentry.register("RememberMe", app => new RememberMeStrategy(app))
  }

}